package net.easyjava.framework.web.security;

import com.alibaba.fastjson.JSONObject;
import net.easyjava.tools.BaseBean;
import net.easyjava.tools.http.request.RequestTools;
import net.easyjava.tools.lang.StringTools;
import net.easyjava.tools.security.aes.AESTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 将用户数据经过双重加密放入到 response 中,具体方法需要子类重写
 * Created by wxnacy on 16/3/7.
 */
public abstract class UserSecurity extends BaseBean {
    private Logger logger = LoggerFactory.getLogger(UserSecurity.class);

    /**
     * 获取request中的用户环境数据
     * @param request
     * @return
     */
    public UserSecurityBean getUserSecurityBean(HttpServletRequest request){
        String aesData = this.readUserSecurity(request);

        if(StringTools.isEmpty(aesData)){
            logger.debug("客户端没有携带用户数据");
            return null;
        }

        UserSecurityBean userSecurityBean = getUserSecurityBean(aesData);
        if(userSecurityBean ==null){
            return null;
        }
        //检查用户id是否被篡改
        String sign = userSecurityBean.getSign();
        String userId = getUserId(sign);
        if(StringTools.isEmpty(userId) || !userSecurityBean.getUserId().equalsIgnoreCase(userId)){
            logger.error(UserSecurityConstants.MESSAGE_USER_ID_BY_SOMEONE_UPDATE,userSecurityBean.getUserId(),userId);
            return null;
        }
        logger.debug("登陆用户信息");
        logger.debug("{}:{}","userId",userSecurityBean.getUserId());
        logger.debug("{}:{}","status",userSecurityBean.getStatus());
        logger.debug("{}:{}","source",userSecurityBean.getSource());
        logger.debug("{}:{}","version",userSecurityBean.getVersion());
        logger.debug("{}:{}","loginTime",userSecurityBean.getLoginTime());
        logger.debug("{}:{}","sign",userSecurityBean.getSign());
        return userSecurityBean;
    }


    /**
     * 设置加密信息,后调用子类方法 操作具体 response 返回数据
     * @param request
     * @param response
     * @param userId
     * @param status
     */
    protected void setUserSecurityBean(String userId,int status , HttpServletRequest request,HttpServletResponse response){
        long begin = System.currentTimeMillis();
        UserSecurityBean userSecurityBean = new UserSecurityBean(userId,status);
        String version = RequestTools.getHeader(request, UserSecurityConstants.API_VERSION);
        String souce = RequestTools.getHeader(request, UserSecurityConstants.API_SOURCE);
        userSecurityBean.setVersion(version);
        userSecurityBean.setSource(souce);
        //获取sign数据
        String sign = getUserIdAesString(userId);
        userSecurityBean.setSign(sign);

        String data = userSecurityBean.toJsonString();
        logger.debug(UserSecurityConstants.USER_SECURITY_LOGIN_DATA,data);
        String aesData = getUserSecurityAesString(data);


        //写入网络环境
        this.writeUserSecurity(response, aesData);
        long end = System.currentTimeMillis();
        logger.debug(UserSecurityConstants.USER_SECURITY_SET_TIME,(end-begin));

    }


    /**
     * 获取UserSecurityBean加密后的数据
     * @param data
     * @return
     */
    protected   String getUserSecurityAesString(String data){
        AESTools aesTools = new AESTools(UserSecurityConstants.KEY_USER_SECURITY);
        try {
            return aesTools.encrypt(data);
        } catch (Exception e) {
            logger.error(UserSecurityConstants.MESSAGE_AES_ENCRYPT_ERROR,"getUserSecurityAesString",data);
            logger.error(e.getMessage(),e.fillInStackTrace());
        }
        return null;
    }

    /**
     * 从加密的数据中获取 UserSecurityBean实例
     * @param aesData
     * @return
     */
    protected   UserSecurityBean getUserSecurityBean(String aesData){
        AESTools aesTools = new AESTools(UserSecurityConstants.KEY_USER_SECURITY);
        try {
            String json = aesTools.decrypt(aesData);
            UserSecurityBean userSecurityBean = JSONObject.parseObject(json, UserSecurityBean.class);
            return userSecurityBean;
        } catch (Exception e) {
            logger.error(UserSecurityConstants.MESSAGE_AES_ENCRYPT_ERROR,"getUserSecurityBean",aesData);
            logger.error(e.getMessage(),e.fillInStackTrace());
        }
        return null;
    }

    /**
     * 获取用户id加密后的数据
     * @param userId
     * @return
     */
    protected String getUserIdAesString(String userId){
        AESTools aesTools = new AESTools(UserSecurityConstants.KEY_USER_SECURITY_ID);
        try {
            return aesTools.encrypt(userId);
        } catch (Exception e) {
            logger.error(UserSecurityConstants.MESSAGE_AES_ENCRYPT_ERROR,"getUserIdAesString",userId);
            logger.error(e.getMessage(),e.fillInStackTrace());
        }
        return null;
    }

    /**
     * 获取用户id 通过加密数据
     * @param aesData
     * @return
     */
    protected String getUserId(String aesData){
        AESTools aesTools = new AESTools(UserSecurityConstants.KEY_USER_SECURITY_ID);
        try {
            String userId = aesTools.decrypt(aesData);
            return userId;
        } catch (Exception e) {
            logger.error(UserSecurityConstants.MESSAGE_AES_ENCRYPT_ERROR,"getUserId",aesData);
            logger.error(e.getMessage(),e.fillInStackTrace());
        }
        return null;
    }
    
    
    
    
    
    
    

    /**
     * 添加长期不过期用户数据
     * @param userId
     * @param status
     * @param request
     * @param response
     */
    public abstract void setLongUserSecurityBean(String userId,int status , HttpServletRequest request,HttpServletResponse response);

    /**
     * 将加密信息写入 response 中
     * @param response
     * @param value
     */
    protected abstract void  writeUserSecurity(HttpServletResponse response,String value);

    /**
     * 获取 request 中的加密信息
     * @param request
     * @return
     */
    protected abstract String readUserSecurity(HttpServletRequest request);
}
